package com.project.visuallinks.client;

import java.util.Set;

import com.google.gwt.core.client.GWT;
import com.google.gwt.json.client.JSONArray;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.json.client.JSONParser;
import com.google.gwt.json.client.JSONValue;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;


import com.google.gwt.http.client.URL;

/*
 * Singleton Class
 * This class is responsible to handle all the calls to the server. It parses the information retrieved.
 */
public class ClientControl {
	public sourceCodeServiceAsync sourceCodeSvc = GWT
			.create(sourceCodeService.class);

	FrontEnd frontEnd = FrontEnd.getFrontEnd();
	public Contact currentContact = Contact.getContact();
	
	private ClientControl() {
	};

	private static class ClientControlHolder {
		private static final ClientControl INSTANCE = new ClientControl();
	}

	public static ClientControl getClientControl() {
		return ClientControlHolder.INSTANCE;
	}

	public void getTop10Tags() {
		// create the URL for the request
		String url = "http://feeds.delicious.com/v2/json/tags/" + currentContact.getName() + "?count=10";
		//ensure a proper encoding of the URL
		url = URL.encode(url);
		//necessary for every server service
		if (sourceCodeSvc == null)
			sourceCodeSvc = GWT.create(sourceCodeService.class);
		
		AsyncCallback<String> callback = new AsyncCallback<String>() {
			public void onFailure(Throwable caught) {
				Window.alert(caught.getMessage());
			}
			public void onSuccess(String result) {
				JSONValue valueJson = JSONParser.parse(result);
				JSONObject objJson = valueJson.isObject();
				int max = 0, tagSize;
				if (objJson == null)
					Window.alert("Could not parse JSON of Get Top 10 tags");
				else {
					// begin to construct the tag objects based on the Json
					// Properties and values
					currentContact.clear();
					Set<String> setKey = objJson.keySet();
					for (int i = 0; i < setKey.size(); i++) {
						tagSize = Integer.parseInt(objJson.get(setKey.toArray()[i].toString()).toString());
						currentContact.addTag(new Tag(setKey.toArray()[i].toString(), tagSize));
						if (max < tagSize)
							max = tagSize;
					}
				}
				//calculate the values for the 3 tag density thresholds
				int temp = max / 3;
				currentContact.setLow(temp);
				currentContact.setMedium(temp * 2);
				currentContact.setHigh(max);
				
				//tell the View to display the mapping according to the Model created here
				FrontEnd.getFrontEnd().displayContact();
			}
		};
		sourceCodeSvc.getTop10Tags(url, callback);
	}
	
public void getRelatedTags(String strTags)
{       
		String url = "http://feeds.delicious.com/v2/json/tags/" + currentContact.getName() + "/" + strTags + "?count=100" ;
		url = URL.encode(url);

		if (sourceCodeSvc == null)
			sourceCodeSvc = GWT.create(sourceCodeService.class);
		
		AsyncCallback<String> callback = new AsyncCallback<String>() {
			public void onFailure(Throwable caught) {
				Window.alert(caught.getMessage());
			}
			public void onSuccess(String result) {
				JSONValue valueJson = JSONParser.parse(result);
				JSONObject objJson = valueJson.isObject();
				FrontEnd.getFrontEnd().strFilter = "All";
				int max = 0;
				int tagSize = 0;
				if (objJson == null)
					Window.alert("Could not parse JSON");
				else {
					// begin to construct the tag objects based on the Json
					// Properties and values
					currentContact.clear();
					Set<String> setKey = objJson.keySet();
					for (int i = 0; i < setKey.size(); i++) {
						tagSize = Integer.parseInt(objJson.get(setKey.toArray()[i].toString()).toString());
						currentContact.addTag(new Tag(setKey.toArray()[i].toString(), tagSize));
						if (max < tagSize)
							max = tagSize;
					}
				}
				//calculate the values for the 3 tag density thresholds
				int temp = max / 3;
				currentContact.setLow(temp);
				currentContact.setMedium(temp * 2);
				currentContact.setHigh(max);
				
				//call the function to display the information on screen
				FrontEnd.getFrontEnd().refreshPath();
				FrontEnd.getFrontEnd().displayRelatedTag();
			}
		};
		sourceCodeSvc.getRelatedTags(url, callback);
}
	
	public void getBookmarks(String tagList) {
		//create the URL for the request
		int nl = currentContact.getTag(currentContact.getSelectedTag()).getNrLinks();
		String url = "http://feeds.delicious.com/v2/json/" + currentContact.getName() + "/" + tagList + "?count=" + String.valueOf(nl);
		//ensure a proper encoding of the URL
		url = URL.encode(url);
		//necessary for every server service
		if (sourceCodeSvc == null)
			sourceCodeSvc = GWT.create(sourceCodeService.class);
		
		AsyncCallback<String> callback = new AsyncCallback<String>() {
			public void onFailure(Throwable caught) {
				Window.alert(caught.getMessage());
			}
			public void onSuccess(String result) {
				JSONValue valueJson = JSONParser.parse(result);
				JSONArray arrayJson = valueJson.isArray();
				if (arrayJson == null)
					Window.alert("Could not parse JSON of Get Bookmarks");
				else {
					// begin to add the links to the tag
					JSONObject objJson;
					int intSelectedTag = currentContact.getSelectedTag();
					//purge the list with the last links
					currentContact.getTag(intSelectedTag).purgeLinksList();
					for (int i = 0; i < arrayJson.size(); i++) {
						objJson = arrayJson.get(i).isObject();
						if (objJson == null) 
						{
							Window.alert("Could not parse JSON of Get Bookmarks");
							return;
						} else 
						{	//construct a new link and add it to the tag
							Links link = new Links();
							link.setDescription(objJson.get("d").toString());
							link.setLink(objJson.get("u").toString());
							link.setTitle(objJson.get("n").toString());
							if (intSelectedTag == -1) return;
							currentContact.getTag(intSelectedTag).addLink(link);
						}
					}
				}
				//call this function to update the Bookmarks list of the FrontEnd
				FrontEnd.getFrontEnd().refreshBookmarks();
			}
		};
		sourceCodeSvc.getBookmarks(url, callback);
		
	}
}
